﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;

namespace DataUploader
{
    class Program
    {
        static void Main(string[] args)
        {
            string pattern =
                        @"^(?n:(?<Apellidos>(?-i:[A-Z]\'?(\w+?|\.)\ ??){1,4})?[\s,\s]*(?<Nombres>(?-i:[A-Z]\'?(\w+?|\.)\ ??){1,4})?)$";
            string splitPattern = @"\s*/\s";

            BibliotecaDataContext bdc = new BibliotecaDataContext();

            var q2 = (from mb in bdc.__mbs
                      group new { mb.Titulo, mb.Clasificacion, mb.Anio } by new { mb.Autor } into agroup
                      select new
                      {
                          Autor = agroup.Key.Autor,
                          Libros = agroup.Distinct()
                      })
            .Distinct();

            //HashSet<Autor> autorSet = new HashSet<Autor>(AutorComparer.Default);
            List<Bib_Autor> autorSet = new List<Bib_Autor>();
            int aID = 1;
            int uno = 1;
            int arID = 0;
            int lID = 1;


            List<Bib_Existencias_por_MatBib> lmb = new List<Bib_Existencias_por_MatBib>();
            List<Bib_MatBib_por_Autor> mbas = new List<Bib_MatBib_por_Autor>();
            List<Bib_MaterialBibliografico> mbs = new List<Bib_MaterialBibliografico>();

            foreach (var item in q2)
            {
                string[] autores = Regex.Split(item.Autor, splitPattern);
                List<int> autoresIDs = new List<int>();

                for (int c = 0; c < autores.Length; c++)
                {
                    Match m = Regex.Match(autores[c], pattern);
                    Bib_Autor a = new Bib_Autor { Nombres = m.Groups["Nombres"].Value, Apellidos = m.Groups["Apellidos"].Value };


                    var contains = (from ast in autorSet where ast.Nombres.Equals(a.Nombres) && ast.Apellidos.Equals(a.Apellidos) select ast).Count();
                    if (contains == 0)
                    {
                        //IMPORTANTE!
                        a.ID = aID++;
                        autorSet.Add(a);
                        autoresIDs.Add(a.ID);
                    }
                    else
                    {
                        arID = (from ast in autorSet where ast.Nombres.Equals(a.Nombres) && ast.Apellidos.Equals(a.Apellidos) select ast.ID).First();
                        autoresIDs.Add(arID);
                    }
                }

                //autoresIDs.Dump();

                foreach (var lib in item.Libros)
                {
                    Bib_MaterialBibliografico mb = new Bib_MaterialBibliografico
                    {
                        //IMPORTANTE!
                        ID = lID++,
                        Titulo = lib.Titulo,
                        Clasificacion = lib.Clasificacion,
                        AnioPublicacion = lib.Anio ?? 2999,
                        TipoMatBibID = uno
                    };
                    mbs.Add(mb);
                    for (int i = 0; i < autoresIDs.Count(); i++)
                    {
                        mbas.Add(new Bib_MatBib_por_Autor { MatBibID = mb.ID, AutorID = autoresIDs[i], EsPrincipal = false });
                    }
                }
                Console.WriteLine();
            }



            bdc.Bib_Autors.InsertAllOnSubmit(autorSet);
            bdc.SubmitChanges();

            bdc.Bib_MaterialBibliograficos.InsertAllOnSubmit(mbs);
            bdc.SubmitChanges();

            bdc.Bib_MatBib_por_Autors.InsertAllOnSubmit(mbas);
            bdc.SubmitChanges();



            string splitPattern2 = @"\s*/\s*";

            var q3 = (from mb in bdc.__mbs
                      group new { Ingreso = mb.NroIngreso, CodigoBarras = mb.CodBarras, Anio = mb.Anio, Titulo = mb.Titulo } by new { mb.Clasificacion } into agroup
                      select new
                      {
                          Clasificacion = agroup.Key.Clasificacion,
                          Existencias = agroup.Distinct()
                      })
                    .Distinct();
            //q3.Dump();

            HashSet<Existencias_por_MatBib> exists = new HashSet<Existencias_por_MatBib>();

            foreach (var item in q3)
            {
                foreach (var ex in item.Existencias)
                {
                    string[] ingresos = Regex.Split(ex.Ingreso, splitPattern2);
                    string[] codigobarras = Regex.Split(ex.CodigoBarras, splitPattern2);
                    if (ingresos.Count() == codigobarras.Count())
                        for (int i = 0; i < ingresos.Count(); i++)
                        {
                            if (!string.IsNullOrEmpty(ingresos[i]))
                                exists.Add(new Existencias_por_MatBib
                                {
                                    Clasificacion = item.Clasificacion,
                                    NumeroIngreso = ingresos[i],
                                    CodigoBarras = codigobarras[i],
                                    Anio = ex.Anio,
                                    Titulo = ex.Titulo
                                });
                        }
                }
            }


            int lmbID = 1;

            var matbibs = from m in bdc.Bib_MaterialBibliograficos select m;

            foreach (var exs in exists)
            {
                foreach (var matbib in matbibs)
                {
                    if (matbib.Clasificacion.Equals(exs.Clasificacion) && exs.Anio == matbib.AnioPublicacion && exs.Titulo.Equals(matbib.Titulo))
                    {
                        lmb.Add(new Bib_Existencias_por_MatBib
                        {
                            ID = lmbID++,
                            MatBibID = matbib.ID,
                            NumeroIngreso = exs.NumeroIngreso,
                            FechaIngreso = DateTime.Now,
                            CodigoBarras = exs.CodigoBarras, // no se agrega por el momento
                            Habilitado = true
                        });
                    }
                }
            }

            bdc.Bib_Existencias_por_MatBibs.InsertAllOnSubmit(lmb.Distinct());
            bdc.SubmitChanges();
        }
    }

    class AutorComparer : IEqualityComparer<Autor>
    {
        #region IEqualityComparer<Autor> Members

        public bool Equals(Autor x, Autor y)
        {
            return x.GetHashCode() == y.GetHashCode();
        }

        public int GetHashCode(Autor obj)
        {
            return obj.GetHashCode();
        }

        #endregion

    }

    class Autor
    {
        public string Nombres { get; set; }
        public string Apellidos { get; set; }
        public override string ToString()
        {
            return string.Format("{0}, {1}", Apellidos, Nombres);
        }
        public override int GetHashCode()
        {
            return (Apellidos + Nombres).GetHashCode();
        }

    }

    class MaterialBibliografico
    {
        public string Titulo { get; set; }
        public string Clasificacion { get; set; }
        public int Tipo { get { return 1; } }
    }

    public class Existencias_por_MatBib
    {
        public string Clasificacion;
        public string NumeroIngreso;
        public string CodigoBarras;
        public string Titulo;
        public int? Anio;
    }
}
